package com.csot.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.csot.ry.domain.TTotalSegment;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import com.csot.model.CityIp;
import com.csot.model.CitySegment;
import com.csot.model.CoarseIp;
import com.csot.model.CoarseSegment;
import com.csot.model.IdleSegment;
import com.csot.model.TotalIp;
import com.csot.model.TotalSegment;
import com.jfinal.plugin.ehcache.CacheKit;
import com.csot.common.utils.StringUtils;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.map.BiMap;
import cn.hutool.core.net.NetUtil;

@Service
public class CoarseIdleIpService {

    private static final Logger log = LoggerFactory.getLogger(CoarseIdleIpService.class);

    protected TotalIp tiDao = new TotalIp().dao();
    protected CityIp ciDao = new CityIp().dao();
    protected CitySegment csDao = new CitySegment().dao();
    protected TotalSegment tsDao = new TotalSegment().dao();
    protected CoarseSegment cssDao = new CoarseSegment().dao();
    protected CoarseIp csiDao = new CoarseIp().dao();

    public List<TotalSegment> handleByCity(String ipType, String city) {
        // TODO Auto-generated method stub
        List<TotalSegment> dataList = new ArrayList<>();

        List<IdleSegment> segmentList = getAllSegment(ipType, city);

        List<TotalSegment> totalSegmentList = segmentList.stream().filter(f -> "total".equals(f.getKb())).map(m -> {
            TotalSegment t = new TotalSegment();
            BeanUtils.copyProperties(m, t);
            return t;
        }).collect(Collectors.toList());

        List<CitySegment> citySegmentList = segmentList.stream().filter(f -> "city".equals(f.getKb())).map(m -> {
            CitySegment c = new CitySegment();
            BeanUtils.copyProperties(m, c);
            return c;
        }).collect(Collectors.toList());

        dataList.addAll(this.getIdleIpSegmentNew(totalSegmentList, citySegmentList));

        List<TotalSegment> totalSegments = new ArrayList<>();
        zhongjian:
        for (TotalSegment ts : dataList) {
            for (CitySegment cs : citySegmentList) {
                if (ts.getIpStartI() >= cs.getIpStartI()
                        && ts.getIpEndI() <= cs.getIpEndI()) {
                    continue zhongjian;
                }
            }
            totalSegments.add(ts);
        }

        return totalSegments;
    }

    protected List<IdleSegment> getAllSegment(String ipType, String city) {


        String sql1 = "select id,ip_start_i,ip_end_i,'total' as kb from t_total_segment ts WHERE ip_type = ? and ip_city = ? order by ip_start_i";
        String sql2 = "select id,ip_start_i,ip_end_i,'city' as kb from t_coarse_segment ts WHERE ip_type = ? and ip_city = ? order by ip_start_i";

        List<Record> records = new ArrayList<>();
        List<Record> tsList = Db.find(sql1, ipType, city);
        List<Record> cityList = Db.find(sql2, ipType, city);
//        List<TotalSegment> totalSegments = new ArrayList<>();

        long start_i = 0;
        long end_i = 0;

        for (int i = 0; i < tsList.size(); i++) {
            Record ts = tsList.get(i);
            if (i == 0) {
                start_i = ts.getLong("ip_start_i");
                end_i = ts.getLong("ip_end_i");

                if (i == tsList.size() - 1) {
                    records.add(ts);
                }
                continue;
            }
            if (i == tsList.size() - 1) {
                if (ts.getLong("ip_start_i") == end_i + 1) {
                    end_i = ts.getLong("ip_end_i");
                } else {
                    Record temp = new Record();
                    BeanUtils.copyProperties(ts, temp, "id");
                    temp.set("ip_city", city);
                    temp.set("ip_end", NetUtil.longToIpv4(ts.getLong("ip_end_i")));
                    temp.set("ip_start", NetUtil.longToIpv4(ts.getLong("ip_start_i")));
                    temp.set("kb", "total");
                    records.add(temp);
                }
            } else {
                if (ts.getLong("ip_start_i") == end_i + 1) {
                    end_i = ts.getLong("ip_end_i");
                    continue;
                }
            }

            ts.set("ip_start", NetUtil.longToIpv4(start_i));
            ts.set("ip_end", NetUtil.longToIpv4(end_i));
            start_i = ts.getLong("ip_start_i");
            end_i = ts.getLong("ip_end_i");
            ts.set("ip_start_i", NetUtil.ipv4ToLong(ts.getStr("ip_start")));
            ts.set("ip_end_i", (NetUtil.ipv4ToLong(ts.getStr("ip_end"))));
            records.add(ts);
        }

        start_i = 0;
        end_i = 0;


        for (int i = 0; i < cityList.size(); i++) {
            Record ts = cityList.get(i);
            if (i == 0) {
                start_i = ts.getLong("ip_start_i");
                end_i = ts.getLong("ip_end_i");

                if (i == cityList.size() - 1) {
                    records.add(ts);
                }
                continue;
            }
            if (i == cityList.size() - 1) {
                if (ts.getLong("ip_start_i") == end_i + 1) {
                    end_i = ts.getLong("ip_end_i");
                } else {
                    Record temp = new Record();
                    BeanUtils.copyProperties(ts, temp, "id");
                    temp.set("ip_city", city);
                    temp.set("ip_end", NetUtil.longToIpv4(ts.getLong("ip_end_i")));
                    temp.set("ip_start", NetUtil.longToIpv4(ts.getLong("ip_start_i")));
                    temp.set("kb", "city");
                    records.add(temp);
                }
            } else {
                if (ts.getLong("ip_start_i") == end_i + 1) {
                    end_i = ts.getLong("ip_end_i");
                    continue;
                }
            }

            ts.set("ip_start", NetUtil.longToIpv4(start_i));
            ts.set("ip_end", NetUtil.longToIpv4(end_i));
            start_i = ts.getLong("ip_start_i");
            end_i = ts.getLong("ip_end_i");
            ts.set("ip_start_i", NetUtil.ipv4ToLong(ts.getStr("ip_start")));
            ts.set("ip_end_i", (NetUtil.ipv4ToLong(ts.getStr("ip_end"))));
            records.add(ts);
        }

        return records.stream().map(m -> {
            IdleSegment is = new IdleSegment();
//            BeanUtils.copyProperties(m, is);
            is.setIpStart(m.getStr("ip_start"));
            is.setIpStartI(m.getLong("ip_start_i"));
            is.setIpEnd(m.getStr("ip_end_i"));
            is.setIpEndI(m.getLong("ip_end_i"));
            is.setKb(m.get("kb"));
            is.setIpType(ipType);
            is.setIpCity(city);
            return is;
        }).collect(Collectors.toList());
    }

    public List<TotalSegment> select(List<TotalSegment> list, TotalSegment bean) {
        return list.stream().filter(f -> {
            if (bean.getIpStartI() != null && f.getIpStartI() >= bean.getIpStartI()) {
                return true;
            }
            if (bean.getIpEndI() != null && f.getIpEndI() <= bean.getIpEndI()) {
                return true;
            }
            if (StringUtils.isNotBlank(bean.getIpType()) && bean.getIpType().equals(f.getIpType())) {
                return true;
            }
            return false;
        }).collect(Collectors.toList());
    }

    // 需要把网络类型整理一下
    protected List<TotalSegment> getIdleIpSegmentNew(List<TotalSegment> t1, List<CitySegment> c1) {

        List<IdleVo> list = new LinkedList<>();

        if (t1 != null) {

            // 一行拆分成2条
            for (TotalSegment ts : t1) {
                IdleVo iv1 = new IdleVo();
                BeanUtils.copyProperties(ts, iv1);
                iv1.ip = ts.getIpStartI();
                iv1.flag1 = "start";
                iv1.flag2 = "total";
                iv1.sort = 1;
                list.add(iv1);

                IdleVo iv2 = new IdleVo();
                BeanUtils.copyProperties(ts, iv2);
                iv2.ip = ts.getIpEndI();
                iv2.flag1 = "end";
                iv2.flag2 = "total";
                iv2.sort = 4;
                list.add(iv2);
            }
        }

        if (c1 != null) {
            for (CitySegment cs : c1) {
                IdleVo iv1 = new IdleVo();
                BeanUtils.copyProperties(cs, iv1);
                iv1.ip = cs.getIpStartI();
                iv1.flag1 = "start";
                iv1.flag2 = "city";
                iv1.sort = 2;
                list.add(iv1);

                IdleVo iv2 = new IdleVo();
                BeanUtils.copyProperties(cs, iv2);
                iv2.ip = cs.getIpEndI();
                iv2.flag1 = "end";
                iv2.flag2 = "city";
                iv2.sort = 3;
                list.add(iv2);
            }
        }

        // 按照ip整型从小到大排序
        Collections.sort(list, (p1, p2) -> {
            if (p1.ip.equals(p2.ip)) {
                return p1.sort - p2.sort;
            } else {
                return p1.ip.compareTo(p2.ip);
            }
        });


        List<IdleVo[]> ivList = new LinkedList<>();

        for (int i = 0; i < list.size() - 1; i++) {
            ivList.add(new IdleVo[]{list.get(i), list.get(i + 1)});
        }

        // 排除地址之间和省级尾部到首部的ip
        List<IdleVo[]> l = ivList.stream().filter(f -> {
            // total和city的start相等
            if (!f[0].flag2.equals(f[1].flag2) && f[0].flag1.equals("start") && f[1].flag1.equals("start")
                    && f[0].ip.equals(f[1].ip)) {
                return false;
            }
            // total和city的end相等
            if (!f[0].flag2.equals(f[1].flag2) && f[0].flag1.equals("end") && f[1].flag1.equals("end")
                    && f[0].ip.equals(f[1].ip)) {
                return false;
            }

            // city start - city end交集
            if (f[0].flag2.equals(f[1].flag2) && f[0].flag2.equals("city") && f[0].flag1.equals("start")
                    && f[1].flag1.equals("end")) {
                return false;
            }
            // total start - total end 首尾交接处
            if (f[0].flag2.equals(f[1].flag2) && f[0].flag2.equals("total") && f[0].flag1.equals("end")
                    && f[1].flag1.equals("start")) {
                return false;
            }

            return true;
        }).collect(Collectors.toList());

        // 整理一下就好
        return l.stream().map(m -> {
            TotalSegment ts = new TotalSegment();
            BeanUtils.copyProperties(m[0], ts);
            if (m[0].flag2.equals("city")) {
                ts.setIpStartI(m[0].ip + 1);
            } else {
                ts.setIpStartI(m[0].ip);
            }

            if (m[1].flag2.equals("city")) {
                ts.setIpEndI(m[1].ip - 1);
            } else {
                ts.setIpEndI(m[1].ip);
            }
            ts.setIpStart(NetUtil.longToIpv4(ts.getIpStartI()));
            ts.setIpEnd(NetUtil.longToIpv4(ts.getIpEndI()));
            return ts;
        }).filter(f -> {
            if (f.getIpStartI() <= f.getIpEndI())
                return true;
            return false;
        }).collect(Collectors.toList());

    }

    public static class IdleVo extends TotalSegment {

        Long ip;

        String flag1;

        String flag2;

        int sort;

    }

}
